package com.zym.init.core.plugin.storage;

import cn.hutool.core.date.DateUtil;
import com.zym.init.enums.StorageServiceProviderEnum;
import com.zym.init.core.exception.ServiceException;
import com.zym.init.model.po.StoragePo;
import com.zym.init.model.vo.UploadFileVo;
import com.zym.init.core.plugin.storage.engine.LocalStorage;
import com.zym.init.core.plugin.storage.engine.MinioStorage;
import com.zym.init.core.utils.ConfigUtils;
import com.zym.init.core.utils.SecurityUtils;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

/**
 * 存储驱动类
 */
@Slf4j
public class StorageDriver {

    /**
     * 当前存储引擎ID
     */
    @Getter
    private final Long storageId;

    /**
     * 当前存储引擎
     */
    private final String engine;

    /**
     * 存储引擎配置
     */
    private final Map<String, String> config;

    /**
     * 构造方法
     */
    public StorageDriver() {
        StoragePo s = ConfigUtils.getDefaultStorage();
        if (s == null) {
            throw new ServiceException("未配置默认存储引擎");
        }
        this.storageId = s.getStorageId();
        this.engine = s.getServiceProvider();
        this.config = s.getStorageConfig();
    }

    /**
     * 删除文件
     *
     * @param paths 路径
     */
    public void delete(List<String> paths) {
        // 判断引擎类型
        if (this.engine.equals(StorageServiceProviderEnum.LOCAL.getServiceProvider())) {
            LocalStorage local = new LocalStorage(config);
            local.delete(paths);
        } else if (this.engine.equals(StorageServiceProviderEnum.MINIO.getServiceProvider())) {
            MinioStorage minio = new MinioStorage(config);
            minio.delete(paths);
        }
    }

    /**
     * 上传文件到指定目录
     *
     * @param multipartFile 文件对象
     * @param dir           目录路径 user/avatar
     * @return UploadFileVo
     */
    public UploadFileVo upload(MultipartFile multipartFile, String dir) {
        // 检查 multipartFile 是否为空
        if (multipartFile == null || multipartFile.isEmpty()) {
            throw new ServiceException("上传文件不能为空");
        }

        // 文件名称
        String fileNameAndExt = buildSafeFileName(buildSaveName(multipartFile));

        // 拼接完整路径与文件名
        StringBuilder savePathBuilder = new StringBuilder();
        if (!StringUtils.isBlank(dir)) {
            savePathBuilder.append(dir).append("/");
        }

        // 拼接用户名
        String username = SecurityUtils.getUsername();
        if (StringUtils.isBlank(username)) {
            savePathBuilder.append("anonymity").append("/");
        } else {
            savePathBuilder.append(username).append("/");
        }

        // 拼接时间
        String date = DateUtil.format(new Date(), "yyyyMMdd");
        savePathBuilder.append(date);

        // 完整路径
        String savePath = savePathBuilder.toString();

        // 判断引擎类型
        if (this.engine.equals(StorageServiceProviderEnum.LOCAL.getServiceProvider())) {
            LocalStorage local = new LocalStorage(config);
            local.upload(multipartFile, savePath, fileNameAndExt);
        } else if (this.engine.equals(StorageServiceProviderEnum.MINIO.getServiceProvider())) {
            MinioStorage minio = new MinioStorage(config);
            minio.upload(multipartFile, savePath, fileNameAndExt);
        }

        // 获取原始文件名+扩展名
        String origFileNameAndExt = Objects.requireNonNull(multipartFile.getOriginalFilename());
        if (origFileNameAndExt.isEmpty()) {
            throw new ServiceException("无法获取原始文件名");
        }

        // 获取原始文件名
        String origFileName = origFileNameAndExt.substring(0, origFileNameAndExt.lastIndexOf("."));
        // 获取原始文件扩展名
        String origFileExt = origFileNameAndExt.substring(origFileNameAndExt.lastIndexOf(".")).replace(".", "").toLowerCase();
        // 获取文件的媒体类型
        MediaType mediaType = MediaType.parseMediaType(Objects.requireNonNull(multipartFile.getContentType()));
        // 获取文件名称
        String fileName = fileNameAndExt.substring(0, fileNameAndExt.lastIndexOf("."));
        // 拼接完整路径
        savePath = savePath + "/" + fileNameAndExt;

        // 返回上传结果
        UploadFileVo vo = new UploadFileVo();
        vo.setId(0L);
        vo.setName(fileName);
        vo.setSize(multipartFile.getSize());
        vo.setExtension(origFileExt);
        vo.setUrl(savePath);
        vo.setMediaType(mediaType.toString());
        vo.setOriginalName(origFileName);
        vo.setStorageId(storageId);
        return vo;
    }

    /**
     * 上传文件
     *
     * @param multipartFile 文件对象
     * @return UploadFilesVo
     */
    public UploadFileVo upload(MultipartFile multipartFile) {
        return upload(multipartFile, "");
    }

    /**
     * 构建安全的文件名
     *
     * @param originalName 原始文件名
     * @return 安全的文件名
     */
    private String buildSafeFileName(String originalName) {
        // 移除路径遍历字符
        return originalName.replaceAll("[/\\\\]", "_");
    }

    /**
     * 生成文件名称
     *
     * @param multipartFile 文件对象
     * @return String
     */
    private String buildSaveName(MultipartFile multipartFile) {
        String name = multipartFile.getOriginalFilename();
        String ext = Objects.requireNonNull(name).substring(name.lastIndexOf("."));
        return UUID.randomUUID() + ext.toLowerCase();
    }

}
